<template>
  <div class="image-processor">
    <div class="form-controls">
      <div class="button-group">
        <el-upload :show-file-list="false" :before-upload="handleUpload" accept="image/*">
          <el-button type="primary">上传图片</el-button>
        </el-upload>
        <el-upload :show-file-list="false" :before-upload="handleWatermarkUpload" action="image/*"
          style="margin-left: 10px">
          <el-button type="warning" :disabled="!imageLoaded">
            添加水印
          </el-button>
        </el-upload>
        <el-button type="success" @click="downloadImage" :disabled="!imageLoaded" style="margin-left: 10px;">
          下载处理后的图片
        </el-button>
      </div>
      <el-form ref="formRef" :model="form" label-width="100px">
        <el-form-item label="画布宽度">
          <el-input-number v-model="form.canvasWidth" :min="200" :max="1500" />
        </el-form-item>
        <el-form-item label="画布高度">
          <el-input-number v-model="form.canvasHeight" :min="200" :max="1500" />
        </el-form-item>
        <el-form-item label="背景模糊程度">
          <el-slider v-model="form.blurRadius" :min="0" :max="100" />
        </el-form-item>
        <el-form-item label="背景图缩放">
          <el-slider v-model="form.backgroundScale" :min="50" :max="200" :step="5" />
        </el-form-item>
        <el-form-item label="前景宽度">
          <el-input-number v-model="form.foregroundWidth" :min="100" :max="800" @focus="activeControl = 'width'" />
        </el-form-item>
        <el-form-item label="前景高度">
          <el-input-number v-model="form.foregroundHeight" :min="100" :max="800" @focus="activeControl = 'height'" />
        </el-form-item>
        <el-form-item label="前景圖縮放：">
          <el-slider v-model="form.foregroundImageScale" :min="10" :max="200" />
        </el-form-item>
        <el-form-item label="锁定前景比例">
          <el-switch v-model="form.lockAspectRatio" />
        </el-form-item>
        <el-form-item label="前景边框颜色">
          <el-color-picker v-model="form.borderColor" show-alpha />
        </el-form-item>
        <el-form-item label="前景边框宽度">
          <el-input-number v-model="form.borderWidth" :min="0" :max="20" />
        </el-form-item>
        <el-form-item label="前景圆角半径">
          <el-input-number v-model="form.cornerRadius" :min="0" :max="50" />
        </el-form-item>
        <el-form-item label="水印位置：">
          <el-select v-model="form.watermarkPosition" placeholder="选择位置">
            <el-option label="左上" value="tl" />
            <el-option label="右上" value="tr" />
            <el-option label="左下" value="bl" />
            <el-option label="右下" value="br" />
            <el-option label="中间" value="center" />
          </el-select>
        </el-form-item>
        <el-form-item label="水印大小：">
          <el-slider v-model="form.watermarkScale" :min="5" :max="200" />
        </el-form-item>
        <el-form-item label="水印透明度：">
          <el-slider v-model="form.watermarkOpacity" :min="0" :max="100" />
        </el-form-item>
      </el-form>
    </div>
    <div class="image-processing">
      <el-alert title="画布" type="info" :closable="false" style="height: 32px;margin-bottom: 20px;" />
      <canvas ref="canvasRef" :width="form.canvasWidth" :height="form.canvasHeight" class="canvas" />
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, watch, nextTick } from 'vue'
import { ElForm, ElFormItem, ElUpload, ElButton, ElInputNumber, ElSlider, ElSwitch, ElColorPicker, ElAlert, ElSelect, ElOption } from 'element-plus'
import { canvasRGB } from 'stackblur-canvas'

const canvasRef = ref<HTMLCanvasElement | null>(null)
const imageLoaded = ref(false)
const currentImage = ref<HTMLImageElement | null>(null)
const originalImageSize = reactive({ width: 0, height: 0 })
const activeControl = ref<'width' | 'height' | null>(null)

const form = reactive({
  canvasWidth: 600,
  canvasHeight: 800,
  blurRadius: 20,
  backgroundScale: 100, // 新增背景缩放
  foregroundWidth: 0,
  foregroundHeight: 0,
  lockAspectRatio: true,
  borderColor: '#ffffff',
  borderWidth: 4,
  cornerRadius: 20,
  watermarkScale: 50, // 百分比
  watermarkOpacity: 50,
  watermarkPosition: "center", // tl/tr/bl/br/center
  foregroundImageScale: 100, // 前景圖內部圖片縮放（百分比）
})

const handleUpload = async (file: File) => {
  const reader = new FileReader()
  reader.onload = () => {
    const img = new Image()
    img.src = reader.result as string
    img.onload = () => {
      currentImage.value = img
      imageLoaded.value = true
      // 记录原始尺寸用于锁定比例计算
      originalImageSize.width = img.width
      originalImageSize.height = img.height

      form.foregroundWidth = img.width
      form.foregroundHeight = img.height

      drawImage()
    }
  }
  reader.readAsDataURL(file)
  return false
}
// 绘制图片
const drawImage = () => {
  const canvas = canvasRef.value
  const img = currentImage.value
  if (!canvas || !img || !imageLoaded.value) return

  const ctx = canvas.getContext('2d', { willReadFrequently: true })
  if (!ctx) return

  ctx.clearRect(0, 0, canvas.width, canvas.height)

  // 背景图绘制 (cover 模式 + 用户缩放)
  const canvasAspect = canvas.width / canvas.height
  const imageAspect = img.width / img.height

  let drawWidth, drawHeight
  if (canvasAspect > imageAspect) {
    drawWidth = canvas.width
    drawHeight = drawWidth / imageAspect
  } else {
    drawHeight = canvas.height
    drawWidth = drawHeight * imageAspect
  }

  const scale = form.backgroundScale / 100
  drawWidth *= scale
  drawHeight *= scale
  const offsetX = (canvas.width - drawWidth) / 2
  const offsetY = (canvas.height - drawHeight) / 2
  ctx.drawImage(img, offsetX, offsetY, drawWidth, drawHeight)

  // 模糊背景
  canvasRGB(canvas, 0, 0, canvas.width, canvas.height, form.blurRadius)

  // 前景图绘制
  const fgWidth = Math.min(form.foregroundWidth, canvas.width)
  const fgHeight = Math.min(form.foregroundHeight, canvas.height)
  const fgX = (canvas.width - fgWidth) / 2
  const fgY = (canvas.height - fgHeight) / 2

  drawRoundedImage(ctx, img, fgX, fgY, fgWidth, fgHeight, form.cornerRadius, form.borderColor, form.borderWidth)
  // ===== 水印绘制部分 =====
  if (watermarkImage.value) {
    const wm = watermarkImage.value;
    const scale = form.watermarkScale / 100;
    const opacity = form.watermarkOpacity / 100;
    const wmWidth = wm.width * scale;
    const wmHeight = wm.height * scale;

    let wmX = 0;
    let wmY = 0;

    switch (form.watermarkPosition) {
      case "tl":
        wmX = 10;
        wmY = 10;
        break;
      case "tr":
        wmX = canvas.width - wmWidth - 10;
        wmY = 10;
        break;
      case "bl":
        wmX = 10;
        wmY = canvas.height - wmHeight - 10;
        break;
      case "br":
        wmX = canvas.width - wmWidth - 10;
        wmY = canvas.height - wmHeight - 10;
        break;
      case "center":
        wmX = (canvas.width - wmWidth) / 2;
        wmY = (canvas.height - wmHeight) / 2;
        break;
    }

    ctx.globalAlpha = opacity;
    ctx.drawImage(wm, wmX, wmY, wmWidth, wmHeight);
    ctx.globalAlpha = 1;
  }
}

function drawRoundedImage(
  ctx: CanvasRenderingContext2D,
  img: HTMLImageElement,
  x: number,
  y: number,
  width: number,
  height: number,
  radius: number,
  borderColor: string,
  borderWidth: number
) {
  ctx.save();
  // 裁剪圓角容器
  ctx.beginPath();
  ctx.moveTo(x + radius, y);
  ctx.lineTo(x + width - radius, y);
  ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
  ctx.lineTo(x + width, y + height - radius);
  ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
  ctx.lineTo(x + radius, y + height);
  ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
  ctx.lineTo(x, y + radius);
  ctx.quadraticCurveTo(x, y, x + radius, y);
  ctx.closePath();
  ctx.clip();

  // ====== 內部圖片縮放處理 ======
  const scale = form.foregroundImageScale / 100;
  const drawImgWidth = width * scale;
  const drawImgHeight = height * scale;
  const imgX = x + (width - drawImgWidth) / 2;
  const imgY = y + (height - drawImgHeight) / 2;
  ctx.drawImage(img, imgX, imgY, drawImgWidth, drawImgHeight);

  ctx.restore();

  if (borderWidth > 0) {
    ctx.beginPath();
    ctx.moveTo(x + radius, y);
    ctx.lineTo(x + width - radius, y);
    ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
    ctx.lineTo(x + width, y + height - radius);
    ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
    ctx.lineTo(x + radius, y + height);
    ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
    ctx.lineTo(x, y + radius);
    ctx.quadraticCurveTo(x, y, x + radius, y);
    ctx.closePath();
    ctx.strokeStyle = borderColor;
    ctx.lineWidth = borderWidth;
    ctx.stroke();
  }
}

const watermarkImage = ref(null);
// 添加水印状态与处理函数
const handleWatermarkUpload = async (file) => {
  const reader = new FileReader();
  reader.onload = () => {
    const img = new Image();
    img.src = reader.result;
    img.onload = () => {
      watermarkImage.value = img;
      drawImage();
    };
  };
  reader.readAsDataURL(file);
  return false;
};

// ===== 监听器 =====
watch(() => form.blurRadius, drawImage)
watch(() => form.cornerRadius, drawImage)
watch(() => form.borderWidth, drawImage)
watch(() => form.borderColor, drawImage)
watch(() => form.backgroundScale, drawImage)

watch(() => form.lockAspectRatio, () => {
  if (form.lockAspectRatio && originalImageSize.width && originalImageSize.height) {
    const ratio = originalImageSize.height / originalImageSize.width
    form.foregroundHeight = Math.round(form.foregroundWidth * ratio)
  }
})

watch([() => form.canvasWidth, () => form.canvasHeight], async () => {
  if (!imageLoaded.value) return
  // 等 DOM 更新完成，Canvas 尺寸生效后再重绘
  await nextTick()
  drawImage()
})

watch([() => form.foregroundWidth, () => form.foregroundHeight], drawImage)

watch(() => form.foregroundWidth, (newWidth) => {
  if (form.lockAspectRatio && activeControl.value === 'width') {
    const ratio = originalImageSize.height / originalImageSize.width
    form.foregroundHeight = Math.round(newWidth * ratio)
  }
})

watch(() => form.foregroundHeight, (newHeight) => {
  if (form.lockAspectRatio && activeControl.value === 'height') {
    const ratio = originalImageSize.width / originalImageSize.height
    form.foregroundWidth = Math.round(newHeight * ratio)
  }
})

watch(
  [
    () => form.watermarkScale,
    () => form.watermarkOpacity,
    () => form.watermarkPosition,
  ],
  drawImage
);

watch(() => form.foregroundImageScale, drawImage);

// 下载功能
const downloadImage = () => {
  const canvas = canvasRef.value
  if (!canvas) return
  const link = document.createElement('a')
  link.href = canvas.toDataURL('image/png')
  link.download = 'processed-image.png'
  link.click()
}
</script>

<style scoped>
.image-processor {
  display: flex;
}

.canvas {
  border: 1px solid #ccc;
}

.form-controls {
  margin-right: 20px;
}

.button-group {
  display: flex;
  margin-bottom: 20px;
}

.image-processing {
  display: flex;
  flex-direction: column;
}
</style>
